package com.baiyang.server.control;

import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;


/**
 * @author XVX
 * webSocket的controller层可以接受到客户端的请求
 *
 * websocket链接不同于http链接，spring boot为所有http链接提供单一的controll，但是为每个websocket链接都提供了一个controller
 * 也就是说WebSocketController并不是单例模式的。不能使用autowrite进行依赖注入
 *
 * 解决方法：实现ApplicationContextAware接口，通过接口对成员变量进行赋值
 */
//声明为bean
@Component
//通过该注解可以让spring boot容器知道该bean是一个webSocket的控制器   其中{sid}是客户端回传的信息
@ServerEndpoint("/websocket/{sid}")
public class WebSocketController {
    private static final Logger log = LoggerFactory.getLogger(WebSocketController.class);
    private Session session = null;
    private static ConcurrentHashMap<String,Session> sessions = new ConcurrentHashMap();
    private String flag = "not connect";
    public WebSocketController() {
        System.out.println("create");
    }
    /**
     * @param session  -----  客户端和服务器之间的会话，客户端通过session发送信息给客户端
     * @param sid  -----  客户端建立链接的过程中回传的信息，一般可以用于身份识别
     * 连接建立成功调用的方法，需要@OnOpen声明
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("sid") String sid) {
        this.session = session;
        sessions.put(sid,session);
    }
    /**
     * 当客户端主动断开链接时调用
     */
    @OnClose
    public void onClose(@PathParam("sid") String sid) {
        sessions.remove(sid);
    }
    /**
     * @param message ---- 客户端发送的请求
     * @param session ---- 会话
     * 接受到客户端请求时调用
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println(message);
    }
    /**
     * @param session
     * @param error
     * 处理发生错误时调用
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        error.printStackTrace();
        sessions.remove(session);
    }
    /**
     * @param message --- 将要发送的信息
     * @throws IOException
     * 服务器主动向客户端发送信息
     */
    public static void sendMessage(String message) throws IOException {
        sessions.values().forEach(e->{
            try {
                e.getBasicRemote().sendText(message);
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        });
    }
}

